/*
Коды ошибок:
1: попытка доступа к элементам вне массива;
2: попытка изменить размер массива на число, меньшее 1,
или попытка создать массив с размером, меньшим 1;
3: нехватка памяти;
4: попытка удалить несуществующий массив;
5: попытка использовать несуществующий массив;
6: попытка достать из массива int вместо void* или наоборот.
*/

#include <stdlib.h>
#include "array.h"
#include "../common.h"
#include "memory.h"

#define ERR_OOR 1
#define ERR_SIZE 2
#define ERR_MEM 3
#define ERR_DEL 4
#define ERR_NXST 5
#define ERR_TYPE 6

/*
0 - в ячейке ничего не лежит;
1 - в ячейке находится int;
2 - в ячейке находится void*.
*/
#define NOTHING 0
#define INTVAL 1
#define PTRVAL -1

array_t* array_create( int arrsize)
{
	int i=0;
	array_t *tmp=NULL;
	ASSERT_WITH_CODE( (arrsize>0), ERR_SIZE);
	tmp=(array_t*)my_malloc(sizeof(array_t));
	ASSERT_WITH_CODE( (tmp!=NULL), ERR_MEM);
	tmp->ptr=(struct arr_elem*)my_malloc(arrsize*sizeof(struct arr_elem));
	ASSERT_WITH_CODE( (tmp->ptr!=NULL), ERR_MEM);
	for (i=0;i<arrsize;i++)
	{
		(tmp->ptr+i)->magic_number=NOTHING;
		(tmp->ptr+i)->ptr_val=0;
	}
	tmp->size=arrsize;
	return tmp;
}

void array_delete( array_t** arr)
{
	ASSERT_WITH_CODE( (*arr!=NULL), ERR_DEL);
	my_free((*arr)->ptr);
	(*arr)->ptr=NULL;
	(*arr)->size=0;
	my_free(*arr);
	*arr=NULL;
}

void array_set_elem_int( array_t* arr, int i, int val) 
{
	ASSERT_WITH_CODE( (arr!=NULL), ERR_NXST);
	ASSERT_WITH_CODE( ((i>=0) && (i<arr->size)), ERR_OOR);
	(arr->ptr+i)->int_val=val;
	(arr->ptr+i)->magic_number=INTVAL;
}

void array_set_elem_ptr( array_t* arr, int i, void *val) 
{
	ASSERT_WITH_CODE( (arr!=NULL), ERR_NXST);
	ASSERT_WITH_CODE( ((i>=0) && (i<arr->size)), ERR_OOR);
	(arr->ptr+i)->ptr_val=val;
	(arr->ptr+i)->magic_number=PTRVAL;
}

int array_get_size( array_t *arr) 
{
	ASSERT_WITH_CODE( (arr!=NULL), ERR_NXST);
	return arr->size;
}

void array_resize( array_t* arr, int new_size) 
{
	ASSERT_WITH_CODE( (arr!=NULL), ERR_NXST);
	int i=0;
	ASSERT_WITH_CODE( (new_size>0), ERR_SIZE);
	arr->ptr=(struct arr_elem*)realloc(arr->ptr,new_size*sizeof(struct arr_elem));
	ASSERT_WITH_CODE( (arr->ptr!=NULL), ERR_MEM);
	for (i=arr->size;i<new_size;i++)
	{
		(arr->ptr+i)->magic_number=NOTHING;
		(arr->ptr+i)->ptr_val=0;
	}
	arr->size=new_size;
}

int array_get_elem_int( array_t* arr, int i) 
{
	ASSERT_WITH_CODE( (arr!=NULL), ERR_NXST);
	ASSERT_WITH_CODE( ((i>=0) && (i<arr->size)), ERR_OOR);
	ASSERT_WITH_CODE( ((arr->ptr+i)->magic_number>=0), ERR_TYPE);
	return (arr->ptr+i)->int_val;
}

void* array_get_elem_ptr( array_t* arr, int i) 
{
	ASSERT_WITH_CODE( (arr!=NULL), ERR_NXST);
	ASSERT_WITH_CODE( ((i>=0) && (i<arr->size)), ERR_OOR);
	ASSERT_WITH_CODE( ((arr->ptr+i)->magic_number<=0), ERR_TYPE);
	return (arr->ptr+i)->ptr_val;
}
